package com.sc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sc.domain.PayBill;
import com.sc.domain.PayItem;
import com.sc.domain.PayMeter;
import com.sc.dto.PayBillCreateDTO;
import com.sc.dto.PayBillPageDTO;
import com.sc.dto.PayBillSaveDto;
import com.sc.dto.PayBillUpdateDTO;
import com.sc.mapper.PayBillMapper;
import com.sc.mapper.PayItemMapper;
import com.sc.mapper.PayMeterMapper;
import com.sc.result.PageResult;
import com.sc.service.PayBillService;
import com.sc.service.calculate.CalculationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
@Transactional
public class PayBillServiceImpl extends ServiceImpl<PayBillMapper, PayBill> implements PayBillService {
    @Autowired
    PayItemMapper payItemMapper;
    @Autowired
    PayBillMapper payBillMapper;
    @Autowired
    private CalculationService calculationService;


    @Override
    public PageResult<PayBill> pageQueryBill(PayBillPageDTO payBillPageDTO) {
        // 1. 构建分页对象
        Page<PayBill> page = new Page<>(payBillPageDTO.getPage(), payBillPageDTO.getPageSize());

        // 2. 构建查询条件
        LambdaQueryWrapper<PayBill> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(payBillPageDTO.getBillNumber())) {
            queryWrapper.eq(PayBill::getBillNumber, payBillPageDTO.getBillNumber());
        }
        if (StringUtils.hasText(payBillPageDTO.getBillName())) {
            queryWrapper.like(PayBill::getBillName, payBillPageDTO.getBillName());
        }
        if (StringUtils.hasText(payBillPageDTO.getRoomNumber())) {
            queryWrapper.eq(PayBill::getRoomNumber, payBillPageDTO.getRoomNumber());
        }
        if (StringUtils.hasText(payBillPageDTO.getHouseholdName())) {
            queryWrapper.like(PayBill::getHouseholdName, payBillPageDTO.getHouseholdName());
        }
        if (StringUtils.hasText(payBillPageDTO.getItem())) {
            queryWrapper.eq(PayBill::getItem, payBillPageDTO.getItem());
        }
        if (payBillPageDTO.getStatus() != null) {
            queryWrapper.eq(PayBill::getStatus, payBillPageDTO.getStatus());
        }

        // 3. 执行分页查询
        Page<PayBill> resultPage = payBillMapper.selectPage(page, queryWrapper);

        // 4. 封装返回结果
        return new PageResult<>(resultPage.getTotal(), resultPage.getRecords());
    }

    @Override
    public void createBill(PayBillCreateDTO requestParam) {
        // 1. 数据校验
        validateRequestParam(requestParam);

        // 2. 生成账单编号
        String billNumber = generateBillNumber();

        // 3. 计算总价
        BigDecimal totalAmount = calculateTotalAmount(requestParam);

        // 4. 构建实体对象
        PayBill payBill = buildPayBill(requestParam, totalAmount);
        payBill.setBillNumber(billNumber); // 设置生成的账单编号

        // 5. 保存到数据库
        save(payBill);
    }

    @Override
    public void updateBill(PayBillUpdateDTO requestParam) {
        // 创建目标对象
        PayBill payBill = new PayBill();

        // 使用 Hutool 的 BeanUtil.copyProperties 进行属性拷贝
        BeanUtil.copyProperties(requestParam, payBill);

        //重新计算总价
        BigDecimal totalAmount = calculateTotalAmount(requestParam);
        payBill.setTotalAmount(totalAmount);

        //更新
        updateById(payBill);
    }

    /**
     * 计算总价 更新
     */
    private BigDecimal calculateTotalAmount(PayBillUpdateDTO requestParam) {
        // 定义公式中的变量
        Map<String, Object> variables = new HashMap<>();
        variables.put("仪表量", requestParam.getUsage()); // 仪表量
        variables.put("单价", requestParam.getUnitPrice()); // 单价

        // 调用计算服务
        return calculationService.calculateTotalAmount(requestParam.getFormula(), variables, requestParam.getCalculationPrecision());
    }

    /**
     * 生成账单编号
     */
    private String generateBillNumber() {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss SSS");
        return "BILL-" + now.format(formatter);
    }

    /**
     * 数据校验
     */
    private void validateRequestParam(PayBillCreateDTO requestParam) {
        if (requestParam.getBillNumber().isEmpty()) {
            throw new IllegalArgumentException("账单编号不能为空");
        }
        if (requestParam.getBillName().isEmpty()) {
            throw new IllegalArgumentException("账单名称不能为空");
        }
        if (requestParam.getRoomNumber().isEmpty()) {
            throw new IllegalArgumentException("房间号不能为空");
        }
        if (requestParam.getUnitPrice() == null || requestParam.getUnitPrice().compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("费用单价必须大于0");
        }
        if (requestParam.getUsage() == null || requestParam.getUsage().compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("走字必须大于0");
        }
    }

    /**
     * 计算总价 新增
     */
    private BigDecimal calculateTotalAmount(PayBillCreateDTO requestParam) {
        // 定义公式中的变量
        Map<String, Object> variables = new HashMap<>();
        variables.put("仪表量", requestParam.getUsage()); // 仪表量
        variables.put("单价", requestParam.getUnitPrice()); // 单价

        // 调用计算服务
        return calculationService.calculateTotalAmount(requestParam.getFormula(), variables, requestParam.getCalculationPrecision());
    }

    /**
     * 构建实体对象
     */
    private PayBill buildPayBill(PayBillCreateDTO requestParam, BigDecimal totalAmount) {
        return PayBill.builder()
                .billNumber(requestParam.getBillNumber())
                .billName(requestParam.getBillName())
                .roomNumber(requestParam.getRoomNumber())
                .householdName(requestParam.getHouseholdName())
                .item(requestParam.getItem())
                .unitPrice(requestParam.getUnitPrice())
                .formula(requestParam.getFormula())
                .unit(requestParam.getUnit())
                .calculationPrecision(requestParam.getCalculationPrecision())
                .lateFeeRate(requestParam.getLateFeeRate())
                .scope(requestParam.getScope())
                .totalAmount(totalAmount)
                .startDate(requestParam.getStartDate())
                .endDate(requestParam.getEndDate())
                .remark(requestParam.getRemark())
                .meter(requestParam.getMeter())
                .usage(requestParam.getUsage())
                .status(requestParam.getStatus() != null ? requestParam.getStatus() : 1) // 默认状态为待缴费
                .build();
    }
}
